using System;
using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using MonsterLove.StateMachine;
using MyFrame.Event;
using Platform;
using Platform.CharacterData;
using Platform.Skill.Core;
using Platform.Skill.Deployer;
using Plugin.Tool;
using UnityEngine;
using UnityEngine.InputSystem;

//状态机文档https://github.com/thefuntastic/Unity3d-Finite-State-Machine
public partial class Player : Entity
{
    private readonly HashSet<States> groundStates = new HashSet<States>()
    {
        States.Idle,
        States.Move,
    };

    [Header("移动")]
    private float currentSpeed = 0f;

    [SerializeField]
    float MoveSpeed => stats.moveSpeed.Value;

    // [SerializeField]
    // float accelerationTime = 0.1f; // 6帧加速

    // [SerializeField]
    // float decelerationTime = 0.005f; // 3帧减速

    [Header("Jump Info")]
    [SerializeField] float gravityScale = 5f;
    [SerializeField] float fallGravityScale = 15f;
    [SerializeField] float wallJumpDuration = 0.25f;
    [SerializeField] float jumpButtonPressTime; //跳跃键按压时间
    [SerializeField] float jumpButtonPressDuration = 0.05f; //跳跃键按压最短持续时间
    [SerializeField] float jumpCancelRate = 10f; //跳跃取消的速率
    private bool jumpCancel = false;
    public int maxJumpCount = 2;
    private int jumpCount;
    private bool jumpSwitch = false; //跳跃开关 只有按下又松开上键才 为true

    private bool CanTwoJump => jumpCount < maxJumpCount;

    #region  攻击处理
    protected PlayerAttackCheck attackCheck;
    [Header("反击")]
    public float counterAttackDuration = 0.2f;

    /// <summary>
    /// 正在反击
    /// 进入反击准备true =》 反击false =》 反击结束true
    /// </summary>
    public bool isCounterAttack = false;

    /// <summary>
    /// 攻击停止移动的时间，一个缓冲
    /// </summary>
    private float attackStopMoveTime = 0.1f; //攻击停止移动的时间，一个缓冲

    private bool isBusy = false;

    /// <summary>
    /// 避免idle转move，会导致滑步
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public void SetBusy(float seconds)
    {
        isBusy = true;
        StartCoroutine(BusyCoroutine(seconds));
    }
    
    IEnumerator BusyCoroutine(float seconds)
    {
        yield return new WaitForSeconds(seconds);
        isBusy = false;
    }
    #endregion

    #region 打击感
    [Header("屏幕震动力度")]
    [Range(0.05f, 0.2f)]
    public float shakeCounterFreaze;
    public Vector2 shakeCounterPower;
    public Vector2 shakeSwordPower;
    #endregion


    #region 检测
    [Header("台阶探针")]
    [SerializeField]
    protected Transform stepCheck;

    [SerializeField]
    protected float stepCheckDistance = 0.2f;

    public bool IsStep() =>
        Physics2D.Raycast(
            stepCheck.position,
            Vector2.right * facingDir,
            stepCheckDistance,
            groundLayer
        );

    [SerializeField]
    protected Transform leftGroundCheck;

    [SerializeField]
    protected Transform rightGroundCheck;

    public override bool IsGroundDetected() =>
        Physics2D.Raycast(groundCheck.position, Vector2.down, groundCheckDistance, groundLayer)
        || IsLeftGroundDetected()
        || IsRightGroundDetected();

    public bool IsLeftGroundDetected() =>
        Raycast(leftGroundCheck.position, Vector2.down, groundCheckDistance, groundLayer);

    public bool IsRightGroundDetected() =>
        Raycast(rightGroundCheck.position, Vector2.down, groundCheckDistance, groundLayer);

    protected override void OnDrawGizmos()
    {
        base.OnDrawGizmos();
        Gizmos.DrawRay(stepCheck.position, Vector2.right * facingDir * stepCheckDistance);
        Gizmos.DrawRay(leftGroundCheck.position, Vector2.down * groundCheckDistance);
        Gizmos.DrawRay(rightGroundCheck.position, Vector2.down * groundCheckDistance);
    }

    #endregion

    #region  输入
    public PlayerInput playerInput;
    private float xInput;
    private float yInput;
    #endregion

    #region  技能
    [Header("技能")]
    protected SkillIndicatorMgr skillIndicatorMgr;
    public bool SkillUsed = true;
    public SkillEnum currentSkill = SkillEnum.flySword;

    public GameObject sword;
    public float swordReturnForce = 5;

    private float flyTime;
    public float flyDuration = 0.3f;

    #endregion


    #region 生命周期
    protected override void Awake()
    {
        base.Awake();

        // inputActions = new PlayerInputActions();
        // inputActions.Player.Enable();
        playerInput =  this.GetComponent<PlayerInput>();

        //添加所需模块
        // fx = gameObject.AddComponent<EntityFX>();

        skillIndicatorMgr = gameObject.AddComponent<SkillIndicatorMgr>();

        attackCheck = GetComponentInChildren<PlayerAttackCheck>();
    }

    protected override void Start()
    {
        base.Start();

        InputBinding();
    }

    protected override void Update()
    {
        base.Update();
        HandlerState();

        xInput = 0;
        yInput = 0;
        xInput = MoveVector.x;
        yInput = MoveVector.y;
    }

    /// <summary>
    /// 更新动画相关参数
    /// </summary>
    private void HandlerState()
    {
        // 在动画中使用物体的垂直速度，比如角色跳跃或者落下时的动画。通过这种方式，动画的表现可以更加真实地反映出物体的运动状态
        anim.SetFloat("yVelocity", rb.velocity.y);
        anim.SetFloat("xVelocity", rb.velocity.x); //todo test

        //本该有个地面状态父类，统一处理，这里用状态组代替
        if (groundStates.Contains(fsm.CurrentState))
        {
            if (!IsGroundDetected())
                fsm.ChangeState(States.AirState);
        }
    }
    #endregion



    #region  行为
    //根据鼠标转向
    public void FlipByMouse()
    {
        Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        if (mousePos.x > transform.position.x && facingDir == -1)
        {
            Flip();
        }
        else if (mousePos.x < transform.position.x && facingDir == 1)
        {
            Flip();
        }
    }

    public void Jump()
    {
        if (IsGroundDetected())
        {
            rb.gravityScale = gravityScale;
            // Impulse瞬间力， force持续力
            rb.AddForce(Vector2.up * Tool.GetJumpForce(JumpHeight, rb), ForceMode2D.Impulse);
            fsm.ChangeState(States.AirState);
            jumpCount = 1;
        }
    }

    public void Dash()
    {
        //冲刺方向
        dashDir = Input.GetAxisRaw("Horizontal");

        // 不应该放在技能，这是一个动作
        if (TryUseSkill(SkillEnum.Dash))
        {
            if (dashDir == 0)
            {
                dashDir = facingDir; //只有当玩家没有控制方向时才使用默认朝向
            }
            ChangeState(States.Dash);
        }
    }

    #region 攻击
    private bool TryAttack(States state)
    {
        if (!skillIndicatorMgr.isSkillChoose)
        {
            fsm.ChangeState(state);
            return true;
        }
        return false;
    }
    private void LightAttack()
    {
        if (TryAttack(States.LightDoubleAttack))
        {
            // PlayLightAttackSound().Forget();
        }
    }


    private void HeavyAttack()
    {
        if (TryAttack(States.HeavyDoubleAttack))
        {
            // PlayHeavyAttackSound().Forget();
        }
    }
    private async UniTask PlayHeavyAttackSound()
    {
        await AnimationTool.AwaitAnimAsync(anim);
        switch (heavyDoubleAttackCombo)
        {
            case 0:
                this.Emit<SoundName>(EventEnum.PlayerSound, SoundName.NormalSwordLightAttack1);
                break;
            case 1:
                this.Emit<SoundName>(EventEnum.PlayerSound, SoundName.NormalSwordLightAttack2);
                break;
            case 2:
                this.Emit<SoundName>(EventEnum.PlayerSound, SoundName.NormalSwordLightAttack3);
                break;
        }
    }
    #endregion


    #endregion

    #region 覆盖

    /// <summary>
    /// 直接改变速度
    /// </summary>
    /// <param name="_xVelocity"></param>
    /// <param name="_yVelocity"></param>
    protected override void SetVelocity(float _xVelocity, float _yVelocity = 0)
    {
        currentSpeed = _xVelocity; //主要是为了落地后无缝衔接
        base.SetVelocity(_xVelocity, _yVelocity);
    }

    public override void BeDamage(CharacterStats source, Collider2D other = null)
    {
        if (isCounterAttack)
            return;
        base.BeDamage(source, other);
        this.Emit<SoundName>(EventEnum.PlayerSound, SoundName.NormalOnhit);
    }

    public override void AttackTrigger(Collider2D other)
    {
        base.AttackTrigger(other);
        // 反击的音效
        if (CurrentState == States.CounterAttack)
            this.Emit<SoundName>(EventEnum.PlayerSound, SoundName.NormalSwordLightAttack3);
    }

    public override bool TryUseSkill(out SkillData skillData, SkillEnum _skill, Vector3 targetPos = default)
    {
        //关闭辅助线
        skillIndicatorMgr.CloseSkillIndicator();
        return base.TryUseSkill(out skillData, _skill, targetPos);
    }

    // public override void AttackTrigger()
    // {
    //     base.AttackTrigger();
    //     AttackColliderCheck<Enemy>((enemy) => enemy.BeDamage(stats));
    // }

    #endregion


    #region  技能
    // 必须参数要在 可选参数之前
    public bool OpenSkillIndicator(SkillEnum _skill)
    {
        return skillIndicatorMgr.OpenSkillIndicator(_skill);
    }

    public bool HasSword()
    {
        if (!sword)
            return false;

        sword.GetComponent<ParabolicSkillDeployer>().EndEffect();
        return true;
    }

    #endregion


}
